#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <sys/wait.h>
#include <sys/types.h>
#include <string>
#include <vector>
#include <unistd.h>
#include <unordered_map>
#include <typeinfo>


using std::string;
using std::vector;
using std::unordered_map;
using std::cout;
using std::cin;
using std::endl;

#define DEBUG
#define COMMENDMAXSIZE 1024
#define FORMAT "[%s@%s %s]# "

// 命令行参数表
vector<string> myargv;

// 环境变量表
vector<string> myenv;

// 别名表
unordered_map<string, string> aliastable;

// 最近一次的进程退出码
int lastcode = 0;

void PrintCommendPrompt()
{
  char *pwd = getenv("PWD");
  if (pwd == nullptr)
  {
    perror(""); 
  }

  string cwd = pwd;

  printf(FORMAT, getenv("USER"), getenv("HOSTNAME"), cwd.substr(cwd.rfind("/") + 1).c_str());
  fflush(stdout);
}

void GetCommendLine(string& CommendLine)
{
  string Temp;
  // getline()会返回传入的流对象，会隐式转换为bool，以作判断
  if (std::getline(cin, Temp))
  {
    if (Temp.size() > COMMENDMAXSIZE)
    {
      cout << "Warning: 输入字符数超过" << COMMENDMAXSIZE << "，输入字符数为：" << Temp.size() << endl;
      CommendLine = Temp.substr(0, COMMENDMAXSIZE);
    }
    else
    {
      CommendLine = Temp;
    }
  }

}

string ReplaceAlias(const string& cmd)
{
  // 防止无限递归
  static int recursionDepth = 0;
  if (++recursionDepth > 10)
  {
    cout << "Error: Possible alias recursion detected." << endl;
    recursionDepth = 0;
    return cmd;
  }

  if (aliastable.find(cmd) != aliastable.end())
  {
    string result = aliastable.at(cmd);
    recursionDepth--;
    return result;
  }

  recursionDepth--;
  return cmd;
}

bool BICommendJudgement()
{
  if (myargv.front() == "cd" || myargv.front() == "echo" || myargv.front() == "alias")
  {
    return true;
  }
  return false;
}

void CommendPrase(string CommendLine)
{
  myargv.clear();
  string currentToken;
  bool inQuotes = false; // 当前是否处于引号范围
  char quoteChar = '\0'; // 记录引号类型

  for (size_t i = 0; i < CommendLine.size(); ++i)
  {
    char ch = CommendLine[i];

    if (ch == '"' || ch == '\'')
    {
      // 切换引号状态
      if (!inQuotes)
      {
        inQuotes = true;
        quoteChar = ch;
      }
      else if (ch == quoteChar) // 匹配到结束的引号
      {
        inQuotes = false;
        quoteChar = '\0';
        if (!currentToken.empty())
        {
          myargv.push_back(currentToken);
          currentToken.clear();
        }
      }
    }
    else if (isspace(ch))
    {
      // 如果不在引号内并且currentToken内有字符串
      if (!inQuotes && !currentToken.empty())
      {
        myargv.push_back(currentToken);
        currentToken.clear();
      }
      else if(inQuotes) // 如果空格在引号内，那么将这个空格视为字符串的一部分
      {
        currentToken += ch;
      }
    }
    else // 不是空格或引号，是正常字符
    {
      currentToken += ch;
    } 

  }

    if (!currentToken.empty() || inQuotes)
    {
      myargv.push_back(currentToken);
      if (inQuotes) // 提示用户有未闭合的引号
        cout << "Warning: Unmatched quote found." << endl;
    }
    

    if (!myargv.empty() && !BICommendJudgement())
    {
#ifdef DEBUG
      cout << "Cmd:" << myargv.front() << endl;
#endif

      // 替换别名
      string replacedCmd = ReplaceAlias(myargv[0]);
      if (replacedCmd != myargv[0])
      {
        string newCommendLine = replacedCmd + CommendLine.substr(myargv[0].size());
        CommendPrase(newCommendLine);
        return;
      }
    }

#ifdef  DEBUG
    for (const string& p : myargv)
    {
      cout << "Token:" << p << endl;
    }
#endif
}

void Cd()
{
  if (myargv.size() == 1)
  {
    char* home = getenv("HOME");
    if(home != nullptr && chdir(home) != 0)
    {
      perror("cd error, cannot change to home directory"); 
    }
  }
  else
  {
    string pos = myargv[1];

    if (pos == "-")
    {

    }
    else if (pos == "~")
    {

    }
    else
    {
      if (chdir(pos.c_str()) != 0)
      {
        perror(("cd error, can not change to directory" + pos).c_str());
      }
    }
  }
      // 更新 PWD 环境变量以反映新的工作目录
    char new_pwd[1024];
    if (getcwd(new_pwd, sizeof(new_pwd)) != nullptr)
    {
        setenv("PWD", new_pwd, 1);
    }

}

void Echo()
{
  if (myargv.size() == 2)
  {
    string opt = myargv[1];

    if (opt == "$?")
    {
      cout << lastcode << endl;
      lastcode = 0;
    }
    else if (opt.front() == '$')
    {
      string envName = opt.substr(1);
      const char *env_value = getenv(envName.c_str());
      if (env_value)
        cout << env_value << endl;
    }
    else 
    {
      if (opt.front() == '\"' || opt.front() == '\'')
      {
        opt.pop_back();
        opt.erase(0,1);
      }
      cout << opt << endl;
    }
  }
}

//void AliasAna()
//{
//  string kv = myargv[1];
//  size_t pos = kv.find("=");
//  string k = kv.substr(0, pos);
//  if (pos == kv.rfind("="))
//  {
//    string v = kv.substr(pos);
//    aliastable.emplace(k, v); 
//  }
//
//}
//
//void Alias()
//{
//  if (myargv.size() == 1)
//  {
//    // 打印别名表
//    for (const std::pair<string, string>& kv: aliastable)
//    {
//      cout << kv.first << "=" << kv.second << endl; 
//    }
//  }
//  else if (myargv.size() == 2)
//  {
//    // 添加别名
//    AliasAna();
//    
//    for (const std::pair<string, string>& kv: aliastable)
//    {
//      cout << kv.first << "=" << kv.second << endl; 
//    }
//  }
//}


void AddAlias()
{
  string kv = myargv[1];
  size_t pos = kv.find("=");
  if (pos == string::npos || pos == 0)
    cout << "Error: Invalid alias format. Expected 'key=value'" << endl;
  
  string k = kv.substr(0, pos);
  string v = kv.substr(pos + 1);

  aliastable[k] = v;
}

void PrintAlias()
{
  for (const std::pair<string, string>& kv : aliastable)
    cout << kv.first << "=" << kv.second<< endl;
}

void Alias()
{
  if (myargv.empty())
  {
    cout << "Error: NoCommand Provided." << endl;
  }

  string cmd = myargv.front();
  if (myargv.size() == 1)
    PrintAlias();
  else if (myargv.size() == 2)
  {
    // 添加别名
    AddAlias();
  }
  else 
  {
    cout << "Error: Too many arguments for alias command." << endl;
  }
}


bool CheckandExecuteBICommend()
{
  string cmd = myargv[0];
  if (cmd == "cd")
  {
    Cd();
    return true;
  }
  else if (cmd == "echo")
  {
    Echo();
    return true;
  }
  else if (cmd == "alias")
  {
    Alias();
    return true;
  }

  return false;
}

void Execute()
{
  char *args[myargv.size() + 1];
  
  // 将string转为C语言风格的字符串
  for (size_t i = 0; i < myargv.size(); ++i)
  {
    // c_str()返回const char*, 但是execv需要char* const[],所以需要移除const属性
    args[i] = const_cast<char*>(myargv[i].c_str());
  }
  args[myargv.size()] = nullptr;

  pid_t pid = fork();
  if (pid == -1) 
  {
    perror("fork error\n");
    exit(EXIT_FAILURE);
  }
  else if (pid == 0)
  {
    if (execvp(args[0], args) == -1)
    {
      perror("execvp error");
      exit(EXIT_FAILURE);
    }
  }

  int status;
  int rid = waitpid(pid, &status, 0);
  
  if (rid > 0)
    lastcode = WEXITSTATUS(status);

  if (WIFEXITED(status) != 0 && WEXITSTATUS(status) != 0)
  {
    perror("进程退出错误\n");
  }
}

void InitEnv()
{
  extern char **environ;
  for (int i = 0; environ[i]; ++i)
  {
    myenv.push_back(string(environ[i]));
  }

  for (vector<string>::iterator it = myenv.begin(); it != myenv.end(); ++it)
  {
    putenv(const_cast<char *>((*it).c_str()));
  }
}

int main()
{
  // 导入环境变量
  InitEnv();

  while (true)
  {

    // 1. 首先打印命令行提示词
    PrintCommendPrompt();
    
    // 2. 获取命令行参数
    string CommendLine;
    GetCommendLine(CommendLine);
    if (CommendLine.empty())
      continue;
    
#ifdef DEBUG
    cout << "CommendLine:" << CommendLine << endl;
#endif

    // 3. 进行语法分析
    CommendPrase(CommendLine); 
    
    // 4. 处理内建命令
    if (CheckandExecuteBICommend())
      continue;

    // 4. 执行命令
    if (!myargv.empty())
    {
      Execute();
    }
  
  }

  return 0;
}




